package org.jeecg.modules.dock.handler.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.modules.basic.customer.service.IBasicCustomerService;
import org.jeecg.modules.basic.material.entity.BasicMaterial;
import org.jeecg.modules.basic.material.service.IBasicMaterialService;
import org.jeecg.modules.basic.plant.service.IWmsSapWarehouseMapService;
import org.jeecg.modules.basic.unit.service.IBasicUnitService;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.vo.WmsOutReceiptTaskPage;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTaskMaterial;
import org.jeecg.modules.business.warehouse.entity.vo.WmsInReceiptTaskPage;
import org.jeecg.modules.dock.constant.SystemConstants;
import org.jeecg.modules.dock.entity.dto.request.SaleOutboundRequestDTO;
import org.jeecg.modules.dock.entity.dto.response.SapBaseResponseDTO;
import org.jeecg.modules.dock.enums.DirectionOfInventoryEnum;
import org.jeecg.modules.dock.enums.DockDataStatus;
import org.jeecg.modules.dock.enums.ReceiptsEnum;
import org.jeecg.modules.dock.enums.SapInterfaceTypeEnum;
import org.jeecg.modules.dock.handler.AbstractSapDataHandler;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.service.WorkFlowService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 销售出库单handler
 *
 * @author zhoutong
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class SaleOutboundHandler extends AbstractSapDataHandler<SaleOutboundRequestDTO> {

    private final WorkFlowService workFlowService;
    private final IBasicMaterialService materialService;
    private final IBasicUnitService iBasicUnitService;
    private final IBasicCustomerService iBasicCustomerService;
    private final IWmsSapWarehouseMapService wmsSapWarehouseMapService;
    private final SapCommonService sapCommonService;
    @Value(value = "${wms.config.personnel.sap:}")
    private String personnelSap;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized List<? extends SapBaseResponseDTO> doHandle(List<SaleOutboundRequestDTO> data) {
        List<SapBaseResponseDTO> dtoList = new ArrayList<>();
        log.info("收到销售出库单发货:{},\n共{}条", data, data.size());
        if (CollectionUtil.isEmpty(data)) {
            return dtoList;
        }

        Map<String, String> unitIdMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(data)) {
            List<String> materialCodes = data.stream().map(t -> t.getMaterialCode()).collect(Collectors.toList());
            sapCommonService.verifyExistenceMaterialCode(materialCodes);
            List<String> codes = data.stream().map(t -> t.getUnit()).collect(Collectors.toList());
            unitIdMap = iBasicUnitService.getIdByCodes(codes);
        }

        // 按照交货单号分组，生成任务
        Map<String, List<SaleOutboundRequestDTO>> SaleOutboundRequestDtosMap = data.stream().collect(
                Collectors.groupingBy(SaleOutboundRequestDTO::getDeliveryNote));

        for (String deliveryNote : SaleOutboundRequestDtosMap.keySet()) {
            List<SaleOutboundRequestDTO> saleOutboundRequestDTOS = SaleOutboundRequestDtosMap.get(deliveryNote);
            dtoList.addAll(createTask(saleOutboundRequestDTOS, unitIdMap));
        }
        return dtoList;
    }

    @Override
    public SapInterfaceTypeEnum type() {
        return SapInterfaceTypeEnum.SALE_OUTBOUND_ORDER;
    }

    /**
     * 创建任务
     *
     * @param data
     */
    private List<SapBaseResponseDTO> createTask(List<SaleOutboundRequestDTO> data, Map<String, String> unitIdMap) {
        List<SapBaseResponseDTO> sapBaseResponseList = new ArrayList<>();
        List<WmsOutReceiptTaskMaterial> outList = new ArrayList<>();
        List<WmsInReceiptTaskMaterial> inList = new ArrayList<>();
        for (SaleOutboundRequestDTO dto : data) {
            String wmsBasicWarehouseId = wmsSapWarehouseMapService.getWmsStroeBySapStore(dto.getStoreLocation(), dto.getFactory());
            List<BasicMaterial> list = materialService.list(new LambdaQueryWrapper<BasicMaterial>().eq(BasicMaterial::getCode, dto.getMaterialCode()));
            if (CollectionUtil.isEmpty(list)) {
                throw new JeecgBootException("物料编码【" + dto.getMaterialCode() + "】查不到");
            }
            //销售数量为负数则为销售退货任务
            if (dto.getQuantity().compareTo(BigDecimal.ZERO) < 0) {
                WmsInReceiptTaskMaterial inMaterial = new WmsInReceiptTaskMaterial();
                inMaterial.setOriginalSystemNumber(dto.getDeliveryNote());
                inMaterial.setOriginalSystemLineNumber(dto.getDeliveryNoteLine().toString());
                if (ObjectUtil.isNotNull(dto.getQuantity())) {
                    inMaterial.setPlanQuantity(dto.getQuantity().abs());
                }
                if (ObjectUtil.isNotEmpty(unitIdMap.get(dto.getUnit()))) {
                    inMaterial.setWmsBasicUnitId(unitIdMap.get(dto.getUnit()));
                }
                inMaterial.setWmsBasicWarehouseId(wmsBasicWarehouseId);
                if (wmsBasicWarehouseId == null){
                    inMaterial.setSapLocationFactory(dto.getStoreLocation()+"-"+dto.getFactory());
                    inMaterial.setWmsBasicWarehouseId("");
                }
                inMaterial.setSapLocation(dto.getStoreLocation());
                inMaterial.setExtraText(JSON.toJSONString(dto));
                inMaterial.setBatchCode(dto.getBatchNumber());

                // 判断销售订单号是否以00开头
                if (StrUtil.isNotBlank(dto.getSaleOrderNumber())) {
                    if (dto.getSaleOrderNumber().startsWith("00")) {
                        // 去掉00
                        inMaterial.setSaleOrderNumber(dto.getSaleOrderNumber().substring(2));
                    }
                }
                inMaterial.setSaleOrderNumber(dto.getSaleOrderNumber());
                inMaterial.setSaleOrderLineNumber(dto.getSaleOrderLineNumber());
                inMaterial.setCustomerOrderNumber(dto.getCustomerOrderNumber());
                inMaterial.setRemark(dto.getRemark());
                inMaterial.setFactory(dto.getFactory());
                if (CollectionUtil.isNotEmpty(list)) {
                    BasicMaterial basicMaterial = list.get(0);
                    inMaterial.setWmsBasicMaterialId(basicMaterial.getId());
                    if (StringUtils.isNotEmpty(basicMaterial.getAssistantUnitId())) {
                        inMaterial.setUnitAssistId(basicMaterial.getAssistantUnitId());
                        inMaterial.setAssistQuantity(BigDecimal.ONE);
                    }
                }
                inList.add(inMaterial);
            } else {
                WmsOutReceiptTaskMaterial material = new WmsOutReceiptTaskMaterial();
                material.setOriginalSystemNumber(dto.getDeliveryNote());
                material.setOriginalSystemLineNumber(dto.getDeliveryNoteLine().toString());
                if (ObjectUtil.isNotNull(dto.getQuantity())) {
                    material.setPlanQuantity(dto.getQuantity());
                }
                if (ObjectUtil.isNotEmpty(unitIdMap.get(dto.getUnit()))) {
                    material.setWmsBasicUnitId(unitIdMap.get(dto.getUnit()));
                }
                material.setWmsBasicWarehouseId(wmsBasicWarehouseId);
                if (wmsBasicWarehouseId == null){
                    material.setSapLocationFactory(dto.getStoreLocation()+"-"+dto.getFactory());
                    material.setWmsBasicWarehouseId("");
                }
                material.setExtraText(JSON.toJSONString(dto));

                material.setBatchCode(dto.getBatchNumber());
                // 判断销售订单号是否以00开头
                if (StrUtil.isNotBlank(dto.getSaleOrderNumber())) {
                    if (dto.getSaleOrderNumber().startsWith("00")) {
                        // 去掉00
                        material.setSaleOrderNumber(dto.getSaleOrderNumber().substring(2));
                    }
                }

                material.setSaleOrderNumber(dto.getSaleOrderNumber());
                material.setSaleOrderLineNumber(dto.getSaleOrderLineNumber());
                material.setCustomerOrderNumber(dto.getCustomerOrderNumber());
                material.setCarNumber(dto.getPlate());
                material.setRemark(dto.getRemark());
                if (CollectionUtil.isNotEmpty(list)) {
                    BasicMaterial basicMaterial = list.get(0);
                    material.setWmsBasicMaterialId(basicMaterial.getId());

                    material.setBlNo(dto.getBlNo());
                    material.setBoxNo(dto.getBoxNo());
                    material.setTitleNo(dto.getTitleNo());

                    if (ObjectUtil.isNotEmpty(basicMaterial)) {
                        if (StringUtils.isNotEmpty(basicMaterial.getAssistantUnitId())) {
                            material.setUnitAssistId(basicMaterial.getAssistantUnitId());
                            material.setAssistQuantity(BigDecimal.ONE);
                        }
                    }
                    outList.add(material);
                }
            }
        }

        String customId = iBasicCustomerService.getIdByCode(data.get(0).getCustom());
        if (ObjectUtil.isNotEmpty(outList)) {
            WmsOutReceiptTaskPage wmsOutReceiptTaskPage = new WmsOutReceiptTaskPage();
            wmsOutReceiptTaskPage.setOrganization("A04A01");
            wmsOutReceiptTaskPage.setDocumentType(ReceiptsEnum.C27.getCode());
            wmsOutReceiptTaskPage.setSysOrgCode("A04A01");
            wmsOutReceiptTaskPage.setOwnerType("1");
            wmsOutReceiptTaskPage.setOwner("A05");
            wmsOutReceiptTaskPage.setDocumentCode(FillRuleUtil.executeRule(DirectionOfInventoryEnum.OUTBOUND.getCode(), JSON.parseObject(DirectionOfInventoryEnum.OUTBOUND.getRemark())).toString());
            wmsOutReceiptTaskPage.setWmsOutReceiptTaskMaterialList(outList);
            wmsOutReceiptTaskPage.setOriginalSystem(SystemConstants.SAP);
            wmsOutReceiptTaskPage.setRequestTime(DateUtil.formatTime(new Date()));
            wmsOutReceiptTaskPage.setRequestPerson(DirectionOfInventoryEnum.OUTBOUND.getSource());
            wmsOutReceiptTaskPage.setCreateBy(personnelSap);
            wmsOutReceiptTaskPage.setTaskDate(DateUtil.parseDate(DateUtil.now()));
            wmsOutReceiptTaskPage.setCustomer(customId);

            if (CollectionUtil.isNotEmpty(wmsOutReceiptTaskPage.getWmsOutReceiptTaskMaterialList())) {
                WmsOutReceiptTaskMaterial taskMaterial = wmsOutReceiptTaskPage.getWmsOutReceiptTaskMaterialList().get(0);
                wmsOutReceiptTaskPage.setOriginalSystemNumber(taskMaterial.getOriginalSystemNumber());
            }
            BaseFlowDto baseFlowDto = new BaseFlowDto();
            baseFlowDto.setBusinessType(ReceiptsEnum.C27.getType());
            baseFlowDto.setDocumentType(ReceiptsEnum.C27.getCode());
            baseFlowDto.setCode(ReceiptsEnum.C27.getRemark());
            baseFlowDto.setData(wmsOutReceiptTaskPage);

            SapBaseResponseDTO outSapBaseResponse = new SapBaseResponseDTO();
            try {
                workFlowService.commit(baseFlowDto);
                outSapBaseResponse.setResult(DockDataStatus.SUCCESS.getCode());
                outSapBaseResponse.setUuid(data.get(0).getUuid());
            } catch (Exception e) {
                outSapBaseResponse.setResult(DockDataStatus.FAILURE.getCode());
                outSapBaseResponse.setUuid(data.get(0).getUuid());
                outSapBaseResponse.setMessage("生成销售出库任务异常");
                log.error("销售出库单出错: {}", e.toString());
            }
            sapBaseResponseList.add(outSapBaseResponse);
        }


        if (ObjectUtil.isNotEmpty(inList)) {
            WmsInReceiptTaskPage wmsInReceiptTaskPage = new WmsInReceiptTaskPage();
            wmsInReceiptTaskPage.setOrganization("A04A01");
            wmsInReceiptTaskPage.setDocumentType(ReceiptsEnum.R28.getCode());
            wmsInReceiptTaskPage.setSysOrgCode("A04A01");
            wmsInReceiptTaskPage.setOwnerType("1");
            wmsInReceiptTaskPage.setOwner("A05");
            wmsInReceiptTaskPage.setOriginalSystem(SystemConstants.SAP);
            wmsInReceiptTaskPage.setRequestTime(new Date());
            wmsInReceiptTaskPage.setRequestPerson(DirectionOfInventoryEnum.OUTBOUND.getSource());
            wmsInReceiptTaskPage.setCreateBy(DirectionOfInventoryEnum.OUTBOUND.getSource());
            wmsInReceiptTaskPage.setDocumentCode(FillRuleUtil.executeRule(DirectionOfInventoryEnum.STORAGE.getCode(), JSON.parseObject(DirectionOfInventoryEnum.STORAGE.getRemark())).toString());
            wmsInReceiptTaskPage.setWmsInReceiptTaskMaterialList(inList);
            wmsInReceiptTaskPage.setTaskDate(DateUtil.parseDate(DateUtil.now()));
            wmsInReceiptTaskPage.setWmsBasicSupplierId(customId);
            if (CollectionUtil.isNotEmpty(wmsInReceiptTaskPage.getWmsInReceiptTaskMaterialList())) {
                WmsInReceiptTaskMaterial taskMaterial = wmsInReceiptTaskPage.getWmsInReceiptTaskMaterialList().get(0);
                wmsInReceiptTaskPage.setOriginalSystemNumber(taskMaterial.getOriginalSystemNumber());
            }
            BaseFlowDto baseFlowDto = new BaseFlowDto();
            baseFlowDto.setBusinessType(ReceiptsEnum.R28.getType());
            baseFlowDto.setDocumentType(ReceiptsEnum.R28.getCode());
            baseFlowDto.setCode(ReceiptsEnum.R28.getRemark());
            baseFlowDto.setData(wmsInReceiptTaskPage);

            SapBaseResponseDTO inSapBaseResponse = new SapBaseResponseDTO();
            try {
                workFlowService.commit(baseFlowDto);
                inSapBaseResponse.setResult(DockDataStatus.SUCCESS.getCode());
                inSapBaseResponse.setUuid(data.get(0).getUuid());
            } catch (Exception e) {
                inSapBaseResponse.setResult(DockDataStatus.FAILURE.getCode());
                inSapBaseResponse.setUuid(data.get(0).getUuid());
                inSapBaseResponse.setMessage("生成销售出库任务异常");
                log.error("销售出库单出错: {}", e.toString());
            }
            sapBaseResponseList.add(inSapBaseResponse);
        }

        return sapBaseResponseList;
    }

}